﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Core.ChannelProtocol;
using Core.Helper;
using Core.Model;
using Core.Model.Transmit;
using Core.Msg;
using Core.Transmit;
using DataServer.Dao;
using DataServer.Dao.Transmit;
using DataServer.Global;
using DataServer.Server;
using log4net;
using Channel = Core.Model.Channel;
using Timer = System.Timers.Timer;

namespace DataServer
{
    public static class AppManager
    {

        #region 外部引入方法

        [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
        public static extern int SetProcessWorkingSetSize(int hProcess, int dwMinimumWorkingSetSize,
            int dwMaximumWorkingSetSize); // 设置内存大小，用于压缩

        //SetProcessWorkingSetSize((int)System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);  // 设置进程最小内存空间

        #endregion

        #region 字段属性

        private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        public static event EventHandler OnCommunicationRestart;

        public static Timer _timer;
        private static int _tickCount;
        // ReSharper disable once NotAccessedField.Local
        private static MainWindow _mainWindow;

       
        public static ChannelDao ChannelDao { get; private set; }
        public static DeviceDao DeviceDao { get; private set; }
        public static DeviceCategoryDao DeviceCategoryDao { get; private set; }
        public static DeviceTypeDao DeviceTypeDao { get; private set; }
        public static DataItemDao DataItemDao { get; private set; }
        public static RemoteItemDao RemoteItemDao { get; private set; }
        public static OperationDao OperationDao { get; private set; }
        public static UserDao UserDao { get; private set; }
        public static HisDataDao HisDataDao { get; private set; }
        public static PageInfoDao PageInfoDao { get; private set; }
        public static ScriptInfoDao ScriptInfoDao { get; private set; }
        public static EventDao EventDao { get; private set; }
        public static RightDao RightDao { get; private set; }
        public static OperRecordDao OperRecordDao { get; private set; }
        public static ResourceDao ResourceDao { get; set; }

        // 转发相关
        public static TransmitChannelDao TransmitChannelDao { get; private set; }
        public static TransmitDeviceDao TransmitDeviceDao { get; private set; }
        public static TransmitDataDao TransmitDataDao { get; private set; }
        public static List<TransmitChannelProtocol> TransmitChannels = new List<TransmitChannelProtocol>();

        public static List<BaseChannel> Channels = new List<BaseChannel>();
        private static readonly Dictionary<string, RealTimeData> _realTimeDatas = new Dictionary<string, RealTimeData>();
        private static readonly object _synRealTimeObj = new object();
        public static bool IsInit { get; private set; }
        public static bool IsRunning =>!Channels.TrueForAll(sss => sss.Running == false);//是否运行中
        public static MsgCtrl MsgCtrl { get; set; } = new MsgCtrl();

        internal static BackgroundWorker _recordDataThread;  // 数据存储线程
        private static DateTime _curMonth = DateTime.Now;   // 存储时间 
        internal static BackgroundWorker _reportGenWorker; // 报表生成线程
        internal static BackgroundWorker _realTimeDataWorker; // 报表生成线程
        internal static Queue<RealTimeData> _realTimeDataToBeUpdate = new Queue<RealTimeData>();
        internal static object _synRealTimeDataUpdate = new object();

        private static readonly ServiceHost _host = new ServiceHost(typeof(ControlService));
        private static readonly ServiceHost _pushHost = new ServiceHost(typeof(PushService));
        /// <summary>
        /// 初始化
        /// </summary>
        static AppManager()
        {
            ChannelDao = new ChannelDao();
            DeviceDao = new DeviceDao();
            DeviceCategoryDao = new DeviceCategoryDao();
            DeviceTypeDao = new DeviceTypeDao();
            DataItemDao = new DataItemDao();
            RemoteItemDao = new RemoteItemDao();
            OperationDao = new OperationDao();       
            UserDao = new UserDao();
            HisDataDao = new HisDataDao();
            PageInfoDao = new PageInfoDao();
            ScriptInfoDao = new ScriptInfoDao();
            EventDao = new EventDao();
            RightDao = new RightDao();
            OperRecordDao = new OperRecordDao();
            ResourceDao = new ResourceDao();

            TransmitChannelDao = new TransmitChannelDao();
            TransmitDeviceDao = new TransmitDeviceDao();
            TransmitDataDao = new TransmitDataDao();

            // 全局访问接口
            Core.Global.DataAccess = new DataAccess();
            Core.Global.NetAccess = new NetAccess();

            _timer = new Timer {Interval = 10000, Enabled = true};
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
        }


        #endregion

        #region 窗体相关

        public static void InitMainWindow(MainWindow mainWindow)
        {
            _mainWindow = mainWindow;
        }

        #endregion

        #region 定时任务

        private static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!CheckRegister()) // 过期
            {
                _timer.Stop();
                StopCommunication();
                Application.Current.Dispatcher?.InvokeShutdown();
            }


            _tickCount++;
            if (_tickCount > 180)//360
            {
                try
                {
                    _tickCount = 0;
                    SetProcessWorkingSetSize((int)Process.GetCurrentProcess().Handle, -1, -1);
                }
                catch
                {
                }
            }
        }

        private static bool hasLogTryUse = false;
        private static bool CheckRegister()
        {
            if (!RegisterHelper.IsRegisted)
            {
                if (!RegisterHelper.CheckRegisteState())
                {
                    if ((DateTime.Now - RegisterHelper.TryDateTime).Hours >= RegisterHelper.TryHours)
                    {
                        _log.Error("软件未注册，试用时间已到期,请联系供应商获取授权码!");
                        return false;
                    }

                    if (!hasLogTryUse)
                    {
                        hasLogTryUse = true;
                        _log.Error($"软件未注册,只能试用{RegisterHelper.TryHours}小时,请联系供应商获取授权码!");
                    }
                   
                }
            }
            else
            {
                if (RegisterHelper.CheckIsExpire()) // 过期  
                {
                    if ((DateTime.Now - RegisterHelper.TryDateTime).Hours >= RegisterHelper.TryHours)
                    {
                        _log.Error("软件已过授权时间,试用时间已到期,请联系供应商获取授权码!");
                        return false;
                    }
                    if (!hasLogTryUse)
                    {
                        hasLogTryUse = true;
                        _log.Error($"软件已过授权时间,只能试用{RegisterHelper.TryHours}小时,请联系供应商获取授权码!");
                    }
                }
            }
            return true;
        }
        #endregion

        #region 设备通信管理
        /// <summary>
        /// 设备初始化,载入通道协议
        /// </summary>
        /// <returns></returns>
        public static bool Initialize()
        {
            try
            {
                Channels.Clear();
                List<Channel> channels = ChannelDao.GetEntities();
                if (channels != null)
                {
                    string strPath = Properties.Resources.chlprotocolpath;
                    DirectoryInfo driverPath = new DirectoryInfo(strPath);
                    FileInfo[] files = driverPath.GetFiles();
                    foreach (Channel ch in channels)
                    {
                        for (int i = 0; i < files.Length; i++)
                        {
                            bool bfind = false;
                            FileVersionInfo info = FileVersionInfo.GetVersionInfo(files[i].FullName);
                            if (info.ProductName != ch.ChannelType) continue;
                            if (files[i].Name.Contains(".dll") || files[i].Name.Contains(".DLL"))
                            {
                                string proPath = Path.Combine(strPath, files[i].Name);
                                Assembly asm = Assembly.Load(new AssemblyName() { CodeBase = proPath });
                                foreach (Type extype in asm.GetExportedTypes())
                                {
                                    //确定type为类并且继承自(实现)BaseChannel
                                    if (extype.IsClass && typeof(BaseChannel).IsAssignableFrom(extype))
                                    {
                                        BaseChannel protocol = (BaseChannel)Activator.CreateInstance(extype, new object[] { ch});
                                        Channels.Add(protocol);
                                        bfind = true;
                                        break;
                                    }
                                }
                                if (bfind)
                                    break;
                            }
                        }
                     
                    }
                }
                try
                {
                    OnCommunicationRestart?.Invoke(null, EventArgs.Empty);
                }
                catch
                {
                }
                return true;
            }
            catch (Exception e)
            {
                _log.Error("通道加载异常:" + e.Message);
            }

            return false;
        }
        /// <summary>
        /// 单独载入某个通道的信息
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        private static bool LoadChannel(Channel channel)
        {
            if (channel ==null) return false;
            try
            {
                string strPath = Properties.Resources.chlprotocolpath;
                DirectoryInfo driverPath = new DirectoryInfo(strPath);
                FileInfo[] files = driverPath.GetFiles();
                for (int i = 0; i < files.Length; i++)
                { 
                    FileVersionInfo info = FileVersionInfo.GetVersionInfo(files[i].FullName);
                    if (info.ProductName != channel.ChannelType) continue;
                    if (files[i].Name.Contains(".dll") || files[i].Name.Contains(".DLL"))
                    {
                        string proPath = Path.Combine(strPath, files[i].Name);
                        Assembly asm = Assembly.Load(new AssemblyName() { CodeBase = proPath });
                        foreach (Type type in asm.GetExportedTypes())
                        {
                            //确定type为类并且继承自(实现)BaseDevProtocol
                            if (type.IsClass && typeof(BaseChannel).IsAssignableFrom(type))
                            {
                                BaseChannel protocol = (BaseChannel)Activator.CreateInstance(type, new object[] { channel });
                                Channels.Add(protocol);
                                return true;
                            }
                        }
                       
                    }
                }
            }
            catch (Exception e)
            {
                _log.Error("通道加载异常:" + e.Message);
            }
            return false;
        }
        /// <summary>
        /// 添加内存中的通道信息
        /// </summary>
        /// <param name="channel"></param>
        public static void AddMemChannel(Channel channel)
        {
            if(channel==null)return;
            foreach (BaseChannel chl in Channels)
            {
                if (chl.ChlInfo.Id == channel.Id)
                {
                    return;
                }
            }

            LoadChannel(channel);
        }
        /// <summary>
        /// 删除内存中的通道信息
        /// </summary>
        /// <param name="channel"></param>
        public static void DelMemChannel(Channel channel)
        {
            if (channel == null) return;
            BaseChannel delChannel = null;
            foreach (BaseChannel chl in Channels)
            {
                if (chl.ChlInfo.Id == channel.Id)
                {
                    delChannel = chl;
                    break;
                }
            }

            if (delChannel != null)
                Channels.Remove(delChannel);
        }
        /// <summary>
        /// 启动通信
        /// </summary>
        /// <returns></returns>
        public static bool StartCommunication(bool reload = true)
        {
            if (reload) Initialize(); // 重新载入信息
            StartDealRealTimeData(); // 实时数据处理
            foreach (IChannel channel in Channels)
            {
                try
                {
                    if (channel.Start())
                    {
                        _log.Info("通道通信任务启动成功:" + channel.ChlInfo.Name + "!");
                    }
                    else
                    {
                        _log.Error("通道通信任务启动失败:" + channel.ChlInfo.Name + "!");
                    }
                    Thread.Sleep(5);
                }
                catch (Exception e)
                {
                    _log.Error("通道通信任务启动异常:" + channel.ChlInfo.Name + "!" + e.Message);
                }
            }
            IsInit = true;
            StartRecordDataThread(); // 数据存储线程
            return true;
        }
        /// <summary>
        /// 停止通信
        /// </summary>
        /// <returns></returns>
        public static bool StopCommunication()
        {
            foreach (IChannel channel in Channels)
            {
                try
                {
                    channel.Stop();
                    _log.Info("通道通信任务成功停止:" + channel.ChlInfo.Name + "!");
                }
                catch (Exception e)
                {
                    _log.Error("通道通信任务停止失败:" + channel.ChlInfo.Name + "!" + e.Message);
                }
            }
            StopRecordDataThread();
            StopDealRealTimeData();
            return true;
        }
        /// <summary>
        /// 重启通信
        /// </summary>
        /// <returns></returns>
        public static bool RestartCommunication()
        {

            StopCommunication();
            bool res = Initialize(); // 重新载入信息
            StartDealRealTimeData();  // 实时数据处理
            foreach (IChannel channel in Channels)
            {
                try
                {
                    if (channel.Start())
                        _log.Info("通道通信任务成功重启:" + channel.ChlInfo.Name + "!");
                    else
                        _log.Error("通道通信任务重启失败:" + channel.ChlInfo.Name + "!");
                    Thread.Sleep(20);
                }
                catch (Exception e)
                {
                    res = false;
                    _log.Error("通道通信任务重启失败:" + channel.ChlInfo.Name + "!" + e.Message);
                }
            }
           
            StartRecordDataThread(); // 数据存储线程
           
            return res;
        }

        /// <summary>
        /// 通过设备获取内存中设备的数据项列表
        /// </summary>
        /// <param name="dev"></param>
        /// <returns></returns>
        public static List<DataItem> GetDataItemsByDevice(Device dev)
        {
            try
            {
                if (dev == null) return null;
                BaseChannel channel = Channels.First(sss => sss.ChlInfo.Id == dev.ChannelId);
                if (channel == null) return null;
                return channel.GetDevProtocolByDevice(dev)?.DataItems;
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 通过设备Id获取内存中的设备
        /// </summary>
        /// <param name="chlId"></param>
        /// <param name="devId"></param>
        /// <returns></returns>
        public static Device GetDeviceById(string chlId,string devId)
        {
            if (Channels.Count == 0) return null;
            BaseChannel channel = Channels.First(sss => sss.ChlInfo.Id == chlId);
            return channel?.GetDeviceById(devId);
        }
        /// <summary>
        /// 修改数值
        /// </summary>
        /// <param name="devId"></param>
        /// <param name="dataId"></param>
        /// <param name="value"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static OperateResult ModifyDataValue(string devId, string dataId,double value,int timeout)
        {
            if (Channels.Count == 0) return new OperateResult(eResult.S_NOT_FOUND,"没有找到指定通道!");
            Device device =DeviceDao.GetEntityById(devId); // 数据库中的设备
            if (device == null)
            {
                return new OperateResult(eResult.S_NOT_FOUND, "没有找到指定设备!");
            }
            BaseChannel channel = Channels.First(sss => sss.ChlInfo.Id == device.ChannelId);
            if(channel==null) return new OperateResult(eResult.S_NOT_FOUND, "没有找到指定通道!");
            Device dev = channel.GetDeviceById(devId); // 内存中的设备
            if(dev==null || dev.GetBaseDevProtocol() == null) return new OperateResult(eResult.S_NOT_FOUND, "没有找到指定设备!");
            RxTxCommand cmd = dev.GetBaseDevProtocol().WriteValue(dataId, value);
            if (timeout < 3) timeout = 500;
            if (WaitForCommand(cmd, timeout))
            {
                return  new OperateResult(eResult.S_OK,"数值修改成功!");
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "数值修改失败!");
            }
        }
        /// <summary>
        /// 修改数值
        /// </summary>
        /// <param name="chlId"></param>
        /// <param name="devId"></param>
        /// <param name="dataId"></param>
        /// <param name="value"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static OperateResult ModifyDataValue(string chlId,string devId, string dataId, double value, int timeout)
        {
            if (Channels.Count == 0) return new OperateResult(eResult.S_NOT_FOUND, "没有找到指定通道!");
            BaseChannel channel = Channels.First(sss => sss.ChlInfo.Id == chlId);
            if (channel == null) return new OperateResult(eResult.S_NOT_FOUND, "没有找到指定通道!");
            Device dev = channel.GetDeviceById(devId); // 内存中的设备
            if (dev == null|| dev.GetBaseDevProtocol()==null) return new OperateResult(eResult.S_NOT_FOUND, "没有找到指定设备!");
            RxTxCommand cmd = dev.GetBaseDevProtocol().WriteValue(dataId, value);
            if (timeout < 3) timeout = 500;
            if (WaitForCommand(cmd, timeout))
            {
                return new OperateResult(eResult.S_OK, "数值修改成功!");
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "数值修改失败!");
            }
        }
        /// <summary>
        /// 直接发送字符串报文
        /// </summary>
        /// <param name="chlId"></param>
        /// <param name="devId"></param>
        /// <param name="content"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static RxTxCommand DirectSendContent(string chlId, string devId, string content, int timeout)
        {
            if (string.IsNullOrEmpty(content)) return null;
            try
            {
                BaseChannel channel = Channels.First(sss => sss.ChlInfo.Id == chlId);
                if (channel == null) return null;
                Device dev = channel.GetDeviceById(devId);
                if (dev == null) return null;
                RxTxCommand cmd = dev.GetBaseDevProtocol().SendMessage(content);
                if (timeout < 3) timeout = 500;
                WaitForCommand(cmd, timeout);
                return cmd;
            }
            catch
            {
                return null;
            }
           
        }
        /// <summary>
        /// 直接发送字节报文
        /// </summary>
        /// <param name="chlId"></param>
        /// <param name="devId"></param>
        /// <param name="content"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static RxTxCommand DirectSendContent(string chlId, string devId, byte[] content, int timeout)
        {
            if (content==null || content.Length==0) return null;
            try
            {
                BaseChannel channel = Channels.First(sss => sss.ChlInfo.Id == chlId);
                if (channel == null) return null;
                Device dev = channel.GetDeviceById(devId);
                if (dev == null) return null;
                RxTxCommand cmd = dev.GetBaseDevProtocol().SendMessage(content);
                if (timeout < 3) timeout = 500;
                WaitForCommand(cmd, timeout);
                return cmd;
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 开始存储数据
        /// </summary>
        /// <returns></returns>
        private static bool StartRecordDataThread()
        {
            _recordDataThread = new BackgroundWorker();
            _recordDataThread.WorkerSupportsCancellation = true;
            _recordDataThread.DoWork += _recordDataThread_DoWork; 
            _recordDataThread.RunWorkerCompleted += _recordDataThread_RunWorkerCompleted; 
            _recordDataThread.RunWorkerAsync();
            return true;
        }
        /// <summary>
        /// 停止存储数据
        /// </summary>
        private static void StopRecordDataThread()
        {
            _recordDataThread?.CancelAsync();
        }

        private static void _recordDataThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (_recordDataThread != null)
            {
                _recordDataThread.DoWork -= _recordDataThread_DoWork;
                _recordDataThread.RunWorkerCompleted -= _recordDataThread_RunWorkerCompleted; 
            }
        }
        /// <summary>
        /// 数据存储线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void _recordDataThread_DoWork(object sender, DoWorkEventArgs e)
        {
            while (!_recordDataThread.CancellationPending)
            {
                _curMonth = DateTime.Now;
                if (!HisDataDao.IsExitTabble(_curMonth))
                {
                    HisDataDao.CreateTable(_curMonth);
                }
                DateTime storeTime = new DateTime(_curMonth.Year, _curMonth.Month, _curMonth.Day, _curMonth.Hour,
                    _curMonth.Minute, 0);
                List<HisData> hisDatas = new List<HisData>();
                foreach (BaseChannel channel in Channels)
                {
                   var storeItems = channel.GetStoreDataItems();
                    foreach (DataItem item in storeItems)
                    {
                        var dev = channel.GetDevProtocolByDevice(item.DeviceId).Dev;
                        if (dev.IsConnected && (storeTime.Minute == 0 || (_curMonth - item.LastStoreTime).TotalMinutes >= item.StorageCycle)) // 在线  整点  大于存储周期
                        {
                            item.LastStoreTime = storeTime;
                            hisDatas.Add(new HisData(item.Id,item.DeviceId,item.Category!= Category.即时值,Math.Round(item.CurValue,6), storeTime));
                        }
                    }
                }
                if (hisDatas.Count > 0)
                {
                    try
                    {
                        if (storeTime.Minute == 0)
                            HisDataDao.InsertOrUpdateEntities(hisDatas, storeTime);
                        else
                            HisDataDao.InsertEntities(hisDatas, storeTime);
                        CheckReportGenThread(_curMonth); // 启动报表生成
                    }
                    catch (Exception exception)
                    {
                       _log.Error("数据存储异常:"+exception.Message);
                    }
                }
                Thread.Sleep(50000);
            }
        }

        /// <summary>
        /// 报表生成检查
        /// </summary>
        /// <param name="dateTime"></param>
        private static void CheckReportGenThread(DateTime dateTime)
        {
            if (dateTime.Minute == 0&& _reportGenWorker == null)
            {
                _reportGenWorker = new BackgroundWorker();
                _reportGenWorker.DoWork += _reportGenWorker_DoWork; 
                _reportGenWorker.RunWorkerCompleted += _reportGenWorker_RunWorkerCompleted; 
                _reportGenWorker.RunWorkerAsync(dateTime);
            }
           
        }
        /// <summary>
        /// 生成报表处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void _reportGenWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime receive = (DateTime)e.Argument;
            try
            {
                HisDataDao.GenerateReport(receive, ReportType.Hour);
                if (receive.Hour == 0)
                {
                    HisDataDao.GenerateReport(receive, ReportType.Day);
                    if (receive.Day == 1)
                    {
                        HisDataDao.GenerateReport(receive, ReportType.Month);
                    }
                }
            }
            catch (Exception ex)
            {
                _log.Error("报表生成异常:"+ex.Message);
            }

        }

        private static void _reportGenWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (_reportGenWorker != null)
            {
                _reportGenWorker.DoWork -= _reportGenWorker_DoWork;
                _reportGenWorker.RunWorkerCompleted -= _reportGenWorker_RunWorkerCompleted;
                _reportGenWorker = null;
            }
            
        }

        /// <summary>
        /// 推送websocket消息
        /// </summary>
        /// <param name="key"></param>
        /// <param name="msg"></param>
        public static void SendWebsocketMsg(string key, object msg)
        {
           
        }

        #endregion

        #region 转发管理
        /// <summary>
        /// 启动转发通信
        /// </summary>
        /// <returns></returns>
        public static bool StartTransmit(bool reload = true)
        {
            if (reload) TransmitInitialize(); // 重新载入信息
            foreach (TransmitChannelProtocol channel in TransmitChannels)
            {
                try
                {
                    if (channel.Start())
                    {
                        _log.Info("转发通道通信任务启动成功:" + channel.ChlInfo.Name + "!");
                    }
                    else
                    {
                        _log.Error("转发通道通信任务启动失败:" + channel.ChlInfo.Name + "!");
                    }
                    Thread.Sleep(5);
                }
                catch (Exception e)
                {
                    _log.Error("转发通道通信任务启动异常:" + channel.ChlInfo.Name + "!" + e.Message);
                }
            }
            return true;
        }
        /// <summary>
        /// 停止转发通信
        /// </summary>
        /// <returns></returns>
        public static bool StopTransmit()
        {
            foreach (TransmitChannelProtocol channel in TransmitChannels)
            {
                try
                {
                    channel.Stop();
                    _log.Info("转发通道通信任务成功停止:" + channel.ChlInfo.Name + "!");
                }
                catch (Exception e)
                {
                    _log.Error("转发通道通信任务停止失败:" + channel.ChlInfo.Name + "!" + e.Message);
                }
            }
            return true;
        }
        /// <summary>
        /// 重启转发通信
        /// </summary>
        /// <returns></returns>
        public static bool RestartTransmit()
        {
            StopTransmit();
            bool res = TransmitInitialize(); // 重新载入信息

            foreach (TransmitChannelProtocol channel in TransmitChannels)
            {
                try
                {
                    if (channel.Start())
                        _log.Info("转到通道通信任务成功重启:" + channel.ChlInfo.Name + "!");
                    else
                        _log.Error("转发通道通信任务重启失败:" + channel.ChlInfo.Name + "!");
                    Thread.Sleep(5);
                }
                catch (Exception e)
                {
                    res = false;
                    _log.Error("转发通道通信任务重启失败:" + channel.ChlInfo.Name + "!" + e.Message);
                }
            }
            return res;
        }

        /// <summary>
        /// 转发初始化
        /// </summary>
        /// <returns></returns>
        public static bool TransmitInitialize()
        {
            try
            {
                TransmitChannels.Clear();
                List<TransmitChannel> channels = TransmitChannelDao.GetEntities();
                if (channels != null)
                {
                    string strPath = Properties.Resources.transmitchannelpath;
                    DirectoryInfo driverPath = new DirectoryInfo(strPath);
                    FileInfo[] files = driverPath.GetFiles();
                    foreach (TransmitChannel ch in channels)
                    {
                        for (int i = 0; i < files.Length; i++)
                        {
                            bool bfind = false;
                            FileVersionInfo info = FileVersionInfo.GetVersionInfo(files[i].FullName);
                            if (info.ProductName != ch.ChannelType) continue;
                            if (files[i].Name.Contains(".dll") || files[i].Name.Contains(".DLL"))
                            {
                                string proPath = Path.Combine(strPath, files[i].Name);
                                Assembly asm = Assembly.Load(new AssemblyName() { CodeBase = proPath });
                                foreach (Type extype in asm.GetExportedTypes())
                                {
                                    //确定type为类并且继承自(实现)TransmitChannelProtocol
                                    if (extype.IsClass && typeof(TransmitChannelProtocol).IsAssignableFrom(extype))
                                    {
                                        TransmitChannelProtocol protocol = (TransmitChannelProtocol)Activator.CreateInstance(extype, new object[] { ch });
                                        TransmitChannels.Add(protocol);
                                        bfind = true;
                                        break;
                                    }
                                }
                                if (bfind)
                                    break;
                            }
                        }

                    }
                }
                return true;
            }
            catch (Exception e)
            {
                _log.Error("转发通道协议加载异常:" + e.Message);
            }

            return false;
        }
        /// <summary>
        /// 加载单个转发通道
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        private static bool LoadTransmitChannel(TransmitChannel channel)
        {
            if (channel == null) return false;
            try
            {
                string strPath = Properties.Resources.transmitchannelpath;
                DirectoryInfo driverPath = new DirectoryInfo(strPath);
                FileInfo[] files = driverPath.GetFiles();
                for (int i = 0; i < files.Length; i++)
                {
                    FileVersionInfo info = FileVersionInfo.GetVersionInfo(files[i].FullName);
                    if (info.ProductName != channel.ChannelType) continue;
                    if (files[i].Name.Contains(".dll") || files[i].Name.Contains(".DLL"))
                    {
                        string proPath = Path.Combine(strPath, files[i].Name);
                        Assembly asm = Assembly.Load(new AssemblyName() { CodeBase = proPath });
                        foreach (Type type in asm.GetExportedTypes())
                        {
                            //确定type为类并且继承自(实现)TransmitChannelProtocol
                            if (type.IsClass && typeof(TransmitChannelProtocol).IsAssignableFrom(type))
                            {
                                TransmitChannelProtocol protocol = (TransmitChannelProtocol)Activator.CreateInstance(type, new object[] { channel });
                                TransmitChannels.Add(protocol);
                                return true;
                            }
                        }

                    }
                }
            }
            catch (Exception e)
            {
                _log.Error("转发通道协议加载异常:" + e.Message);
            }
            return false;
        }
        /// <summary>
        /// 添加内存中的通道信息
        /// </summary>
        /// <param name="channel"></param>
        public static void AddMemTransmitChannel(TransmitChannel channel)
        {
            if (channel == null) return;
            foreach (TransmitChannelProtocol chl in TransmitChannels)
            {
                if (chl.ChlInfo.Id == channel.Id)
                {
                    return;
                }
            }

            LoadTransmitChannel(channel);
        }
        /// <summary>
        /// 删除内存中的通道信息
        /// </summary>
        /// <param name="channel"></param>
        public static void DelMemTransmitChannel(TransmitChannel channel)
        {
            if (channel == null) return;
            TransmitChannelProtocol delChannel = null;
            foreach (TransmitChannelProtocol chl in TransmitChannels)
            {
                if (chl.ChlInfo.Id == channel.Id)
                {
                    delChannel = chl;
                    break;
                }
            }

            if (delChannel != null)
                TransmitChannels.Remove(delChannel);
        }

        #endregion

        #region 实时数据处理

        public static void PostData(string itemId,bool privilege, object value)
        {
            lock (_synRealTimeDataUpdate)
            {
                _realTimeDataToBeUpdate.Enqueue(new RealTimeData(itemId,"",value),20000);
            }
        }

        private static bool StartDealRealTimeData()
        {
            var task = Task.Factory.StartNew(() =>
            {
                try
                {
                    _log.Info("开始载入实时运行数据...");
                    lock (_synRealTimeObj)
                    {
                        _realTimeDatas.Clear();
                        var rtData = DataItemDao.GetAllDataItems();
                        foreach (RealTimeData data in rtData)
                        {
                            _realTimeDatas.Add(data.Id, data);
                        }
                    }

                    lock (_synRealTimeObj)
                    {
                        var devices = DeviceDao.GetEntities();
                        foreach (Device dev in devices)
                        {
                            _realTimeDatas.Add(dev.Id, new RealTimeData(dev.Id, dev.Name));
                        }
                    }

                    lock (_synRealTimeObj)
                    {
                        var channels = ChannelDao.GetEntities();
                        foreach (Channel chl in channels)
                        {
                            _realTimeDatas.Add(chl.Id, new RealTimeData(chl.Id, chl.Name));
                        }
                    }
                   
                    _log.Info("完成载入实时运行数据!");

                }
                catch
                {

                }
            });
            
            Task.WaitAll(task);
            _realTimeDataWorker = new BackgroundWorker();
            _realTimeDataWorker.WorkerSupportsCancellation = true;
            _realTimeDataWorker.DoWork += _realTimeDataWorker_DoWork;
            _realTimeDataWorker.RunWorkerCompleted += _realTimeDataWorker_RunWorkerCompleted; 
            _realTimeDataWorker.RunWorkerAsync();
            Thread.Sleep(100);
            return true;
        }

        private static void StopDealRealTimeData()
        {
            _realTimeDataWorker?.CancelAsync();
        }
        private static void _realTimeDataWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            while (!_realTimeDataWorker.CancellationPending)
            {
                lock (_synRealTimeDataUpdate)
                {
                    while (_realTimeDataToBeUpdate.Count > 0)
                    {
                        RealTimeData data = _realTimeDataToBeUpdate.Dequeue();
                        if (data != null && _realTimeDatas.ContainsKey(data.Id))
                        {
                            _realTimeDatas[data.Id].Value = data.Value;
                        }
                    }
                }
                Thread.Sleep(100);
            }
        }

        private static void _realTimeDataWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _realTimeDataToBeUpdate.Clear();
            _realTimeDataWorker.DoWork -= _realTimeDataWorker_DoWork;
            _realTimeDataWorker.RunWorkerCompleted -= _realTimeDataWorker_RunWorkerCompleted; 
        }

        public static List<RealTimeData> GetRealTimeDatas(List<string> ids)
        {
            if (ids == null || ids.Count == 0)
                return null;
            lock (_synRealTimeObj)
            {
                List<RealTimeData> datas = new List<RealTimeData>();
                foreach (string id in ids)
                {
                    if(_realTimeDatas.ContainsKey(id))
                      datas.Add( _realTimeDatas[id]);
                }
                return datas;
            }
        }

        #endregion

        #region WCF服务启停
        /// <summary>
        /// 启动WCF服务
        /// </summary>
        public static void StartWcfService()
        {
            try
            {
                _host.Opened += delegate
                {
                    try
                    {
                        _log.Info($"WCF主服务启动成功！{_host.BaseAddresses[0]}");//
                    }
                    catch
                    {
                    }
                };
                _host.Open();
                try
                {
                    _pushHost.Opened += delegate
                    {
                        try
                        {
                            _log.Info($"WCF推送服务启动成功！");//
                        }
                        catch
                        {
                        }
                    };
                    _pushHost.Open();
                }
                catch (Exception e)
                {
                    _log.Error("WCF推送服务启动出错:" + e.Message);
                }
            }
            catch (Exception e)
            {
                _log.Error("WCF服务启动出错:" + e.Message);
            }
        }
        /// <summary>
        /// 关闭WCF服务
        /// </summary>
        public static void StopWcfService()
        {
            try
            {
                _host.Close(TimeSpan.FromMilliseconds(100));
                _pushHost.Close(TimeSpan.FromMilliseconds(100));
                _log.Info("WCF服务成功关闭!");
            }
            catch (Exception e)
            {
                _log.Error("WCF服务关闭出错:" + e.Message);
            }
        }

        #endregion

        #region 执行命令

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="chlid"></param>
        /// <param name="devid"></param>
        /// <param name="operid"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static OperateResult ExcuteCommand(string chlid, string devid, string operid, int timeout)
        {
            OperateResult result;
            try
            {
                IChannel channel = Channels.Find(sss => sss.ChlInfo.Id == chlid);
                if (channel == null)
                {
                    _log.Info("命令执行失败:没有找到指定的通道!");
                    result = new OperateResult(eResult.S_NOT_FOUND, "没有找到指定的通道!");
                }
                else
                {
                    RxTxCommand cmd = channel.PostToExcute(devid, operid);
                    if (cmd == null)
                    {
                        result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                    }
                    else
                    {
                        if (cmd.NeedReply)
                        {
                            int wait = timeout > 0 ? timeout : 500 + 2 * channel.ChlInfo.PollingDelay;
                            if (WaitForCommand(cmd, wait))
                            {
                                result = new OperateResult(eResult.S_OK, "命令执行成功!", cmd.ReceiveContent);
                            }
                            else
                            {
                                result = new OperateResult(eResult.S_FAILED, "命令执行失败!", cmd.ReceiveContent);
                            }
                        }
                        else
                        {
                            result = new OperateResult(eResult.S_OK, "命令已发送!");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                _log.Warn("命令执行异常:" + e.Message);
            }
            return result;
        }

        /// <summary>
        /// 执行带参数的命令
        /// </summary>
        /// <param name="chlid"></param>
        /// <param name="devid"></param>
        /// <param name="operid"></param>
        /// <param name="paras"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static OperateResult ExcuteCommand(string chlid, string devid, string operid, string paras,int timeout)
        {
            OperateResult result;
            try
            {
                if (string.IsNullOrEmpty(paras))
                {
                    return ExcuteCommand(chlid, devid, operid, timeout);
                }
                string[] parameters = paras.Split(new[] { ',' }, 10, StringSplitOptions.RemoveEmptyEntries);
                if (parameters.Length == 0)
                {
                    return ExcuteCommand(chlid, devid, operid, timeout);
                }
                IChannel channel = Channels.Find(sss => sss.ChlInfo.Id == chlid);
                if (channel == null)
                {
                    _log.Info("命令执行结果:没有找到指定的通道!");
                    result = new OperateResult(eResult.S_NOT_FOUND, "没有找到指定的通道!");
                }
                else
                {
                    RxTxCommand cmd = channel.PostToExcute(devid, operid, parameters);
                    if (cmd == null)
                    {
                        result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                    }
                    else
                    {
                        if (cmd.NeedReply)
                        {
                            int wait = timeout > 0 ? timeout : 500 + 2 * channel.ChlInfo.PollingDelay;
                            if (WaitForCommand(cmd, wait))
                            {
                                result = new OperateResult(eResult.S_OK, "命令执行成功!", cmd.ReceiveContent);
                            }
                            else
                            {
                                result = new OperateResult(eResult.S_FAILED, "命令执行失败!", cmd.ReceiveContent);
                            }
                        }
                        else
                        {
                            result = new OperateResult(eResult.S_OK, "命令已发送!");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                _log.Warn("命令执行异常:" + e.Message);
            }
            return result;
        }

        /// <summary>
        /// 遥控操作
        /// </summary>
        /// <param name="rcId"></param>
        /// <param name="on"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static OperateResult RemoteControlCommand(string rcId, bool on, int timeout)
        {
            OperateResult result;
            try
            {
                var rcItem = RemoteItemDao.GetEntityById(rcId);
                if (rcItem == null)
                {
                    _log.Warn("遥控执行失败:没有找到相关遥控点!");
                    return new OperateResult(eResult.S_NOT_FOUND, "没有找到相关遥控点!");
                }
                else
                {
                    if (rcItem.HasAlarmWin)
                    {
                        _log.Warn("遥控执行失败:当前遥控点光字牌生效中，不允许操作!");
                        return new OperateResult(eResult.S_NOT_FOUND, "光字牌生效中，不允许操作!");
                    }
                }
                DataItem relateItem = RemoteItemDao.GetDataItemByRcId(rcId);
                if (relateItem == null)
                {
                    _log.Warn("遥控执行失败:没有找到关联的数据项!");
                    return new OperateResult(eResult.S_NOT_FOUND, "没有找到关联的数据项!");
                }
                Device device = DataItemDao.GetDeviceById(relateItem.Id);
                if (device == null)
                {
                    _log.Warn("遥控执行失败:没有找到关联的设备!");
                    return new OperateResult(eResult.S_NOT_FOUND, "没有找到关联的设备!");
                }
                IChannel channel = Channels.Find(sss => sss.ChlInfo.Id == device.ChannelId);
                if (channel == null)
                {
                    _log.Warn("遥控执行失败:没有找到关联的通道!");
                    result = new OperateResult(eResult.S_NOT_FOUND, "没有找到指定的通道!");
                }
                else
                {
                    RxTxCommand cmd = channel.RemoteControl(device.Id, rcId, on);
                    if (cmd == null)
                    {
                        _log.Warn("遥控执行失败:执行命令异常!");
                        result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                    }
                    else
                    {
                        if (cmd.NeedReply)
                        {
                            int wait = timeout > 0 ? timeout : 500 + 2 * channel.ChlInfo.PollingDelay;
                            if (WaitForCommand(cmd, wait))
                            {
                                _log.Info("命令执行成功!");
                                result = new OperateResult(eResult.S_OK, "命令执行成功!", cmd.ReceiveContent);
                            }
                            else
                            {
                                _log.Warn("命令执行失败!");
                                result = new OperateResult(eResult.S_FAILED, "命令执行失败!", cmd.ReceiveContent);
                            }
                        }
                        else
                        {
                            _log.Info("命令已发送!");
                            result = new OperateResult(eResult.S_OK, "命令已发送!");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                _log.Warn("命令执行异常:" + e.Message);
            }
            return result;
        }
        

        #endregion

        #region 通过反射调用通道协议中的方法

        public static Dictionary<string, List<string>> GetChannelMethods(string chlid)
        {
            BaseChannel channel = Channels.Find(sss => sss.ChlInfo.Id == chlid);
            return channel?.GetExportMethods();
        }

        public static OperateResult InvokeMethod(string chlid,string method,string paras,int timeout)
        {
            OperateResult result;
            try
            {
                BaseChannel channel = Channels.Find(sss => sss.ChlInfo.Id == chlid);
                if (channel == null)
                {
                    _log.Info("方法调用结果:没有指定通道!");
                    result = new OperateResult(eResult.S_NOT_FOUND, "没有找到指定通道!");
                }
                else
                {
                    if (!channel.GetMethodParas(method).Split(',')[0].Contains("RxTxCommand"))
                    {
                        result = new OperateResult(eResult.S_OK, "执行成功!", channel.InvokeMethod(method, paras));
                        return result;
                    }
                    RxTxCommand cmd = channel.InvokeMethod(method,paras) as RxTxCommand;
                    
                    if (cmd == null)
                    {
                        result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                    }
                    else
                    {
                        channel.PutInsertCommand(cmd); // 放入发送队列
                        if (cmd.NeedReply)
                        {
                            int wait = timeout > 0 ? timeout : 500 + 2 * channel.ChlInfo.PollingDelay;
                            if (WaitForCommand(cmd, wait))
                            {
                                result = new OperateResult(eResult.S_OK, "命令执行成功!", cmd.ReceiveContent);
                            }
                            else
                            {
                                result = new OperateResult(eResult.S_FAILED, "命令执行失败!", cmd.ReceiveContent);
                            }
                        }
                        else
                        {
                            result = new OperateResult(eResult.S_OK, "命令已发送!");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                result = new OperateResult(eResult.S_FAILED, "执行命令异常!");
                _log.Warn("命令执行异常:" + e.Message);
            }
            return result;
        }

       #endregion

        #region 用户操作

        public static OperateResult Login(string name, string password)
        {
           
            User user = UserDao.GetEntityByName(name);
            if (user != null && user.Password == password)
            {
                user.UpdateTime = DateTime.Now;
                UserDao.UpdateEntity(user);
              
                return new OperateResult(eResult.S_OK, "登录成功!"); 
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "登录失败,用户Id错误或密码错误!"); 
            }
        }

        public static OperateResult Logout(string name)
        {
            User user = UserDao.GetEntityByName(name);
            if (user != null)
            {
                UserDao.UpdateEntity(user);
                return new OperateResult(eResult.S_OK, "退出成功!"); 
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "退出失败,没有找到用户!");
            }
        }

        public static OperateResult RegisterUser(User user)
        {
            if (UserDao.InsertEntity(user))
            {
                return new OperateResult(eResult.S_OK, "用户注册成功!");
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "用户注册失败!");
            }
        }

        public static OperateResult UpdateUser(User user)
        {
            if (UserDao.UpdateEntity(user))
            {
                return new OperateResult(eResult.S_OK, "更新用户成功!"); 
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "更新用户失败!");
            }
        }

        public static OperateResult DeleteUser(User user)
        {
            if (UserDao.DeleteEntity(user))
            {
                return new OperateResult(eResult.S_OK, "用户删除成功!");
            }
            else
            {
                return new OperateResult(eResult.S_FAILED, "用户删除失败!");
            }
        }

        public static List<Right> GetAllRights()
        {
            return RightDao.GetEntities();
        }

        public static List<Right> GetUserRights(string userId)
        {
            return RightDao.GetUserRights(userId);
        }

        public static bool UpdateUserRights(string userId,string rightIds)
        {
            string[] ids = string.IsNullOrEmpty(rightIds) ? new string[]{} : rightIds.Split(',');
            return RightDao.UpdateUserRights(userId, ids.ToList());
        }

        public static List<string> GetUserDeviceIds(string userId)
        {
            return RightDao.GetUserDeviceIds(userId);
        }

        public static bool UpdateUserDevices(string userId, string deviceIds)
        {
            string[] ids = string.IsNullOrEmpty(deviceIds) ? new string[] { } : deviceIds.Split(',');
            return RightDao.UpdateUserDevices(userId, ids.ToList());
        }

        public static List<OperRecord> GetOperRecords(string user, DateTime? from, DateTime? to)
        {
            return OperRecordDao.GetOperations(user, from, to);
        }

        public static bool AddUserOperation(OperRecord record)
        {
            return OperRecordDao.InsertEntity(record);
        }
        #endregion

        #region 事件处理

        public static List<Event> GetEvents(EventType type, EventLevel level, bool? isConfirm, DateTime? from, DateTime? to)
        {
            return EventDao.GetEvents(type, level, isConfirm, from, to);
        }

        public static Event AddEvent(EventType type, EventLevel level, string description)
        {
            Event result = null;
            try
            {
                result = new Event()
                {
                    Id = Guid.NewGuid().ToString(), EventTime = DateTime.Now, EventType = type, EventLevel = level,
                    IsConfirm = false, Description = description
                };
                if (EventDao.InsertEntity(result))
                    return result;
                else
                    return null;
            }
            catch
            {
            }
            return result;
        }

        public static bool ConfirmEvent(string[] ids, string man)
        {
            bool result = false;
            try
            {
                result = EventDao.ConfirmEvent(ids, man);
                if (result)
                {
                    PushService.ConfirmEvent(ids);
                }
            }
            catch
            {
            }
            return result;
        }
        #endregion

        #region 公用函数

        private static bool WaitForCommand(RxTxCommand cmd, int timeout)
        {
            int interval = 20;
            if (cmd == null) return false;
            if (timeout <= interval)
            {
                Thread.Sleep(timeout);
                return cmd.ReceiveResult == MsgResult.RecOk;
            }
            int count=0, poll = timeout / interval;
            
            while (count <= poll)
            {
                Thread.Sleep(interval);
                count++;
                if (cmd.ReceiveResult != MsgResult.Undefined)
                {
                    return cmd.ReceiveResult == MsgResult.RecOk;
                }
            }
            return false;
        }

        #endregion
    }
}
